home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / lha_axeman / lharc.c < prev    next >
C/C++ Source or Header  |  1995-09-01  |  19KB  |  811 lines

  1. /*----------------------------------------------------------------------*/
  2. /*        LHarc Archiver Driver for UNIX                                            */
  3. /*        This is part of LHarc UNIX Archiver Driver                            */
  4. /*                                                                                        */
  5. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa                                  */
  6. /*        Thanks to H.Yoshizaki. (MS-DOS LHarc)                                    */
  7. /*                                                                                        */
  8. /*  V0.00  Original                1988.05.23  Y.Tagawa                            */
  9. /*  V0.01  Alpha Version (for 4.2BSD)        1989.05.28  Y.Tagawa              */
  10. /*  V0.02  Alpha Version Rel.2            1989.05.29  Y.Tagawa                  */
  11. /*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa                */
  12. /*  V0.03a Debug                1989.07.03  Y.Tagawa                              */
  13. /*  V0.03b Modified                1989.07.13  Y.Tagawa                            */
  14. /*  V0.03c Debug (Thanks to void@rena.dit.junet)1989.08.09  Y.Tagawa      */
  15. /*  V0.03d Modified (quiet and verbose)        1989.09.14  Y.Tagawa            */
  16. /*  V1.00  Fixed                1989.09.22  Y.Tagawa                              */
  17. /*  V1.01  Bug Fixed                1989.12.25  Y.Tagawa                          */
  18. /*                                                                                        */
  19. /*  DOS-Version Original LHx V C2.01         (C) H.Yohizaki                      */
  20. /*                                                                                        */
  21. /*  V2.00  UNIX Lharc + DOS LHx -> OSK LHx    1990.11.01  Momozou            */
  22. /*  V2.01  Minor Modified            1990.11.24  Momozou                          */
  23. /*                                                                                        */
  24. /*  V0.02  LHx for UNIX                1991.11.18  M.Oki                            */
  25. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki                            */
  26. /*  V0.04  LHa for UNIX    beta version        1992.01.20  M.Oki                  */
  27. /*  V1.00  LHa for UNIX    Fixed            1992.03.19  M.Oki                        */
  28. /*----------------------------------------------------------------------*/
  29.  
  30. #include "lharc.h"
  31.  
  32. /*----------------------------------------------------------------------*/
  33. /*                PROGRAM                                                               */
  34. /*----------------------------------------------------------------------*/
  35. #define CMD_UNKNOWN    0
  36. #define CMD_EXTRACT    1
  37. #define CMD_ADD          2
  38. #define CMD_LIST      3
  39. #define CMD_DELETE    4
  40.  
  41. static int    cmd = CMD_UNKNOWN;
  42. char    **cmd_filev;
  43. int    cmd_filec;
  44.  
  45. char    *archive_name;
  46. char    expanded_archive_name[FILENAME_LENGTH];
  47. char    temporary_name[FILENAME_LENGTH];
  48. char    backup_archive_name[FILENAME_LENGTH];
  49.  
  50. /* static functions */
  51. static void sort_files();
  52.  
  53. /* options */
  54. boolean    quiet = FALSE;
  55. boolean    text_mode = FALSE;
  56. boolean    verbose = FALSE;
  57. boolean    noexec = FALSE;    /* debugging option */
  58. boolean    force = FALSE;
  59. boolean    prof = FALSE;
  60. int compress_method = 5;    /* deafult -lh5- */
  61. int header_level = HEADER_LEVEL1;
  62. #ifdef EUC
  63. boolean euc_mode = FALSE;
  64. #endif
  65.  
  66. /* view command flags */
  67. boolean    verbose_listing = FALSE;
  68.  
  69. /* extract command flags */
  70. boolean    output_to_stdout = FALSE;
  71.  
  72. /* append command flags */
  73. boolean    new_archive = FALSE;
  74. boolean    update_if_newer = FALSE;
  75. boolean    delete_after_append = FALSE;
  76. boolean    generic_format = FALSE;
  77.  
  78. boolean    remove_temporary_at_error = FALSE;
  79. boolean    recover_archive_when_interrupt = FALSE;
  80. boolean    remove_extracting_file_when_interrupt = FALSE;
  81. boolean get_filename_from_stdin = FALSE;
  82. boolean ignore_directory = FALSE;
  83. boolean verify_mode = FALSE;
  84.  
  85. char *extract_directory = NULL;
  86. char **xfilev;
  87. int  xfilec = 257;
  88.  
  89. /*----------------------------------------------------------------------*/
  90. /* NOTES :        Text File Format                                                  */
  91. /*    GENERATOR          NewLine                                                          */
  92. /*    [generic]          0D  0A                                                        */
  93. /*    [MS-DOS]          0D  0A                                                        */
  94. /*    [OS9][MacOS]          0D                                                          */
  95. /*    [UNIX]              0A                                                              */
  96. /*----------------------------------------------------------------------*/
  97.  
  98.  
  99. static void print_tiny_usage_and_exit()
  100. {
  101.   puts("\n\n"
  102.        "AxeLH - v0.01 - ©1994 AxeTech Inc. - Written By AxeMan.\n");
  103.   puts("-------------------------------------------------------\n");
  104.   puts("Options:\n\n");
  105.   puts(" E | X : EXtract\n");
  106.   puts("     L : List\n");
  107.   puts("     A : Add\n");
  108.   puts("-------------------------------------------------------\n");
  109.  
  110.   exit(1);
  111. }
  112.  
  113. void main(int argc, char *argv[])
  114. {
  115.   char *p,
  116.   inpbuf[256];
  117.  
  118.   if(argc < 2) print_tiny_usage_and_exit();
  119.   if(argc < 3)
  120.   {
  121.     cmd = CMD_LIST;
  122.     argv--;
  123.     argc++;
  124.     goto work;
  125.   }
  126.  
  127.   if( argv[1][0]=='-' ) argv[1]++;
  128.  
  129.   /* commands */
  130.   switch(argv[1][0])
  131.   {
  132.     case 'x':
  133.     case 'e':
  134.       cmd = CMD_EXTRACT;
  135.       break;
  136.  
  137.     case 'p':
  138.       output_to_stdout = TRUE;
  139.       cmd = CMD_EXTRACT;
  140.       break;
  141.  
  142.     case 'c':
  143.       new_archive = TRUE;
  144.       cmd = CMD_ADD;
  145.       break;
  146.  
  147.     case 'a':
  148.       cmd = CMD_ADD;
  149.       break;
  150.  
  151.     case 'd':
  152.       cmd = CMD_DELETE;
  153.       break;
  154.  
  155.     case 'u':
  156.       update_if_newer = TRUE;
  157.       cmd = CMD_ADD;
  158.       break;
  159.  
  160.     case 'm':
  161.       delete_after_append = TRUE;
  162.       cmd = CMD_ADD;
  163.       break;
  164.  
  165.     case 'v':
  166.       verbose_listing = TRUE;
  167.       cmd = CMD_LIST;
  168.       break;
  169.  
  170.     case 'l':
  171.       cmd = CMD_LIST;
  172.       break;
  173.  
  174.     case 't':
  175.       cmd = CMD_EXTRACT;
  176.       verify_mode = TRUE;
  177.       break;
  178.  
  179.     default:
  180.       print_tiny_usage_and_exit ();
  181.     
  182.   }
  183.  
  184.   /* options */
  185.   p = &argv[1][1];
  186.  
  187.   for(p = &argv[1][1]; *p; )
  188.   {
  189.     switch ( (*p++) )
  190.       {
  191.           case 'q':    quiet = TRUE; break;
  192.           case 'f':    force = TRUE; break;
  193.           case 'p':    prof = TRUE; break;
  194.           case 'v':    verbose = TRUE; break;
  195.           case 't':    text_mode = TRUE; break;
  196. #ifdef EUC
  197.           case 'e':    text_mode = TRUE; euc_mode = TRUE; break;
  198. #endif
  199.           case 'n':    noexec = TRUE; break;
  200.           case 'g':    generic_format = TRUE; header_level = 0; break;
  201.           case 'd':    delete_after_append = TRUE; break;
  202.           case 'o':    compress_method = 1; header_level = 0; break;
  203.           case 'z':    compress_method = 0; break;
  204.           case 'i':    ignore_directory = TRUE; break;
  205.           case 'w':    if ( *p=='=' ) p++;
  206.                     extract_directory=p;
  207.                     while (*p) p++;
  208.                     break;
  209.           case '0':    header_level = HEADER_LEVEL0; break;
  210.           case '1':    header_level = HEADER_LEVEL1; break;
  211.           case '2':    header_level = HEADER_LEVEL2; break;
  212.           default:
  213.           fprintf(stderr, "LHa: Unknown option '%c'.\n", p[-1]);
  214.           exit(1);
  215.         }
  216.   }
  217.  
  218. work:
  219.   /* archive file name */
  220.   archive_name = argv[2];
  221.  
  222.   if(!strcmp(archive_name, "-"))
  223.   {
  224.     if(!isatty(1) && cmd == CMD_ADD) quiet = TRUE;
  225.   }
  226.   else
  227.   {
  228.     if(argc == 3 && !isatty(0)) get_filename_from_stdin = TRUE;
  229.   }
  230.  
  231.   /* target file name */
  232.   if( get_filename_from_stdin )
  233.   {
  234.       cmd_filec = 0;
  235.       if((xfilev = (char **)malloc(sizeof(char *) * xfilec)) == NULL)
  236.           fatal_error("Virtual memory exhausted\n");
  237.        while ( gets( inpbuf ) )
  238.        {
  239.           if( cmd_filec >= xfilec )
  240.           {
  241.               xfilec += 256;
  242.               cmd_filev = (char **)realloc(xfilev, sizeof(char *) * xfilec);
  243.               if( cmd_filev == NULL )
  244.                   fatal_error("Virtual memory exhausted\n");
  245.               xfilev = cmd_filev;
  246.           }                
  247.            if(strlen( inpbuf )<1 ) continue;
  248.            if((xfilev[cmd_filec++]=(char *)strdup(inpbuf))==NULL )
  249.               fatal_error("Virtual memory exhausted\n");
  250.        }
  251.        xfilev[cmd_filec] = NULL;
  252.        cmd_filev = xfilev;
  253.   }
  254.   else
  255.   {
  256.       cmd_filec = argc - 3;
  257.       cmd_filev = argv + 3;
  258.   }
  259.   sort_files();
  260.  
  261.   /* make crc table */
  262.   make_crctable();
  263.  
  264.   switch(cmd)
  265.   {
  266.     case CMD_EXTRACT:
  267.       cmd_extract();
  268.       break;
  269.     case CMD_ADD:
  270.       cmd_add();
  271.       break;
  272.     case CMD_LIST:
  273.       cmd_list();
  274.       break;
  275.     case CMD_DELETE:
  276.       cmd_delete();
  277.       break;
  278.   }
  279.  
  280.   exit (0);
  281. }
  282.  
  283. static void message_1(char *title, char *subject, char *name)
  284. {
  285.   fprintf(stderr, "LHa: %s%s ", title, subject);
  286.   fflush(stderr);
  287.  
  288.   if(errno == 0)
  289.     fprintf(stderr, "%s\n", name);
  290.   else
  291.     perror(name);
  292. }
  293.  
  294. void message(char *subject, char *name)
  295. {
  296.   message_1("", subject, name);
  297. }
  298.  
  299. void warning(char *subject, char *name)
  300. {
  301.   message_1("Warning: ", subject, name);
  302. }
  303.  
  304. void error(char *subject, char *msg)
  305. {
  306.   message_1("Error: ", subject, msg);
  307. }
  308.  
  309. void fatal_error(char *msg)
  310. {
  311.   message_1("Fatal error:", "", msg);
  312.  
  313.   if(remove_temporary_at_error)
  314.     unlink(temporary_name);
  315.  
  316.   exit(1);
  317. }
  318.  
  319. char *writting_filename;
  320. char *reading_filename;
  321.  
  322. void write_error()
  323. {
  324.   fatal_error(writting_filename);
  325. }
  326.  
  327. void read_error()
  328. {
  329.   fatal_error(reading_filename);
  330. }
  331.  
  332. void interrupt(int signo)
  333. {
  334.   errno = 0;
  335.   message("Interrupted\n", "");
  336.  
  337.   if(temporary_fp) fclose(temporary_fp);
  338.   unlink(temporary_name);
  339.  
  340.   if(recover_archive_when_interrupt) rename(backup_archive_name, archive_name);
  341.   if(remove_extracting_file_when_interrupt)
  342.   {
  343.     errno = 0;
  344.     message("Removing", writting_filename);
  345.     unlink(writting_filename);
  346.   }
  347.   signal(SIGINT, SIG_DFL);
  348.   kill(getpid (), signo);
  349. }
  350.  
  351.  
  352. /*----------------------------------------------------------------------*/
  353. /*                                    */
  354. /*----------------------------------------------------------------------*/
  355.  
  356. static int sort_by_ascii(char **a, char **b)
  357. {
  358.   register char *p, *q;
  359.   register int c1, c2;
  360.  
  361.   p = *a, q = *b;
  362.   if(generic_format)
  363.   {
  364.     do
  365.       {
  366.         c1 = *(unsigned char*)p ++;
  367.         c2 = *(unsigned char*)q ++;
  368.         if(!c1 || !c2)
  369.           break;
  370.         if(islower (c1))
  371.           c1 = toupper (c1);
  372.         if(islower (c2))
  373.           c2 = toupper (c2);
  374.       }
  375.     while (c1 == c2) ;
  376.     return c1 - c2;
  377.   }
  378.   else
  379.   {
  380.     while(*p == *q && *p != '\0') p++, q++;
  381.     return *(unsigned char*)p - *(unsigned char*)q;
  382.   }
  383. }
  384.  
  385. static void sort_files ()
  386. {
  387.   if(cmd_filec > 1) qsort(cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  388. }
  389.  
  390. char *xmalloc(int size)
  391. {
  392.   char *p = (char *)malloc (size);
  393.   if(!p) fatal_error("Not enough memory");
  394.   return p;
  395. }
  396.  
  397. char *xrealloc(char *old, int size)
  398. {
  399.   char *p = (char *)realloc (old, size);
  400.   if(!p) fatal_error("Not enough memory");
  401.   return p;
  402. }
  403.  
  404. /*----------------------------------------------------------------------*/
  405. /*                STRING POOL                */
  406. /*----------------------------------------------------------------------*/
  407.  
  408. /*
  409.  * string pool :
  410.  *    +-------------+-------------+---     ---+-------------+----------+
  411.  *    | N A M E 1 \0| N A M E 2 \0|    ...    | N A M E n \0|             |
  412.  *    +-------------+-------------+---     ---+-------------+----------+
  413.  *    ^                              ^         ^
  414.  * buffer+0                        buffer+used  buffer+size
  415.  */
  416.  
  417. /*
  418.  * vector :
  419.  *    +---------------+---------------+-------------     -------------+
  420.  *    | pointer to    | pointer to    | pointer to   ...  pointer to    |
  421.  *    |  string pool    |  N A M E 1    |  N A M E 2   ...   N A M E n    |
  422.  *    +---------------+---------------+-------------     -------------+
  423.  *    ^        ^
  424.  *   malloc base      returned
  425.  */
  426.  
  427. void init_sp(struct string_pool *sp)
  428. {
  429.   sp->size = 1024 - 8;        /* any ( >=0 ) */
  430.   sp->used = 0;
  431.   sp->n = 0;
  432.   sp->buffer = (char*)xmalloc(sp->size * sizeof (char));
  433. }
  434.  
  435. void add_sp(struct string_pool *sp, char *name, int len)
  436. {
  437.   while (sp->used + len > sp->size)
  438.   {
  439.     sp->size *= 2;
  440.     sp->buffer = (char*) xrealloc (sp->buffer, sp->size * sizeof (char));
  441.   }
  442.   bcopy (name, sp->buffer + sp->used, len);
  443.   sp->used += len;
  444.   sp->n ++;
  445. }
  446.  
  447. void finish_sp(struct string_pool *sp, int v_count, char ***v_vector)
  448. {
  449.   int i;
  450.   register char *p;
  451.   char **v;
  452.  
  453.   v = (char**) xmalloc((sp->n + 1) * sizeof (char*));
  454.   *v++ = sp->buffer;
  455.   *v_vector = v;
  456.   p = sp->buffer;
  457.   for(i = sp->n; i; i --)
  458.   {
  459.     *v++ = p;
  460.     if (i - 1) p+=strlen(p)+1;
  461.   }
  462. }
  463.  
  464. void free_sp(char **vector)
  465. {
  466.   vector --;
  467.   free(*vector);        /* free string pool */
  468.   free(vector);
  469. }
  470.  
  471.  
  472. /*----------------------------------------------------------------------*/
  473. /*            READ DIRECTORY FILES                */
  474. /*----------------------------------------------------------------------*/
  475.  
  476. static boolean include_path_p(char *path, char *name)
  477. {
  478.   char *n = name;
  479.   while(*path)
  480.     if(*path++ != *n++)
  481.       return (path[-1] == '/' && *n == '\0');
  482.   return(*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
  483. }
  484.  
  485. #define STREQU(a,b)    (((a)[0] == (b)[0]) ? (strcmp ((a),(b)) == 0) : FALSE)
  486.  
  487. void cleaning_files(int *v_filec, char ***v_filev)
  488. {
  489.   char *flags;
  490.   struct stat stbuf;
  491.   register char **filev = *v_filev;
  492.   register int filec = *v_filec;
  493.   register char *p;
  494.   register int i, j;
  495.  
  496.   if(filec == 0) return;
  497.  
  498.   flags = xmalloc(filec * sizeof (char));
  499.  
  500.   /* flags & 0x01 :    1: ignore */
  501.   /* flags & 0x02 :    1: directory, 0 : regular file */
  502.   /* flags & 0x04 :    1: need delete */
  503.  
  504.   for(i = 0; i < filec; i ++)
  505.     if(stat(filev[i], &stbuf) < 0)
  506.     {
  507.         flags[i] = 0x04;
  508.       fprintf(stderr, "LHa: Cannot access \"%s\", ignored.\n", filev[i]);
  509.     }
  510.     else
  511.     {
  512.         if(is_regularfile(&stbuf))
  513.         flags[i] = 0x00;
  514.         else if (is_directory(&stbuf))
  515.           flags[i] = 0x02;
  516.         else
  517.         {
  518.           flags[i] = 0x04;
  519.           fprintf(stderr, "LHa: Cannot archive \"%s\", ignored.\n", filev[i]);
  520.         }
  521.     }
  522.     errno = 0;
  523.  
  524.     for(i = 0; i < filec; i ++)
  525.     {
  526.       p = filev[i];
  527.       if((flags[i] & 0x07) == 0x00)
  528.         {            /* regular file, not deleted/ignored */
  529.           for(j = i + 1; j < filec; j ++)
  530.           {
  531.             if((flags[j] & 0x07) == 0x00)
  532.               {        /* regular file, not deleted/ignored */
  533.                 if (STREQU (p, filev[j]))
  534.                 flags[j] = 0x04; /* delete */
  535.               }
  536.           }
  537.         }
  538.       else if ((flags[i] & 0x07) == 0x02)
  539.         {            /* directory, not deleted/ignored */
  540.           for (j = i + 1; j < filec; j ++)
  541.           {
  542.             if ((flags[j] & 0x07) == 0x00)
  543.               {        /* regular file, not deleted/ignored */
  544.                 if (include_path_p (p, filev[j]))
  545.               flags[j] = 0x04; /* delete */
  546.               }
  547.             else if ((flags[j] & 0x07) == 0x02)
  548.               {        /* directory, not deleted/ignored */
  549.                 if (include_path_p (p, filev[j]))
  550.                 flags[j] = 0x04; /* delete */
  551.               }
  552.           }
  553.         }
  554.     }
  555.  
  556.     for (i = j = 0; i < filec; i ++)
  557.     {
  558.       if ((flags[i] & 0x04) == 0)
  559.         {
  560.           if(i != j) filev[j] = filev[i];
  561.           j ++;
  562.         }
  563.     }
  564.     *v_filec = j;
  565.  
  566.   free (flags);
  567. }
  568.  
  569. boolean find_files(char *name, int *v_filec, char ***v_filev)
  570. {
  571.   struct string_pool sp;
  572.   char newname[FILENAME_LENGTH];
  573.   int len, n;
  574.   DIR *dirp;
  575.   DIRENTRY *dp;
  576.   struct stat tmp_stbuf, arc_stbuf, fil_stbuf;
  577.  
  578.   strcpy (newname, name);
  579.   len = strlen (name);
  580.   if(len > 0 && newname[len-1] != '/')
  581.     newname[len++] = '/';
  582.  
  583.   dirp = opendir (name);
  584.   if(!dirp)
  585.     return FALSE;
  586.  
  587.   init_sp (&sp);
  588.  
  589.   GETSTAT(temporary_name, &tmp_stbuf);
  590.   GETSTAT(archive_name, &arc_stbuf);
  591.  
  592.   for(dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  593.   {
  594.       n = NAMLEN (dp);
  595.       strncpy (newname+len, dp->d_name, n);
  596.       newname[len + n] = '\0';
  597.       if (GETSTAT(newname, &fil_stbuf) < 0) continue;
  598.       if ((dp->d_ino != 0) &&
  599.       ((dp->d_name[0] != '.') ||
  600.        ((n != 1) &&
  601.         ((dp->d_name[1] != '.') ||
  602.          (n != 2)))) &&
  603.       ((tmp_stbuf.st_dev != fil_stbuf.st_dev ||
  604.         tmp_stbuf.st_ino != fil_stbuf.st_ino) &&
  605.        (arc_stbuf.st_dev != fil_stbuf.st_dev ||
  606.         arc_stbuf.st_ino != fil_stbuf.st_ino)))
  607.  
  608.     {
  609.       add_sp (&sp, newname, len + n + 1);
  610.     }
  611.     }
  612.   closedir (dirp);
  613.   finish_sp(&sp, v_filec, v_filev);
  614.   if (*v_filec > 1)
  615.     qsort (*v_filev, *v_filec, sizeof (char*), sort_by_ascii);
  616.   cleaning_files (v_filec, v_filev);
  617.  
  618.   return TRUE;
  619. }
  620.  
  621. void free_files(int filec, char **filev)
  622. {
  623.   free_sp(filev);
  624. }
  625.  
  626. /*----------------------------------------------------------------------*/
  627. /*                                    */
  628. /*----------------------------------------------------------------------*/
  629.  
  630. /* Build temporary file name and store to TEMPORARY_NAME */
  631. void build_temporary_name()
  632. {
  633.   char *p,
  634.        *s;
  635.  
  636.   strcpy (temporary_name, archive_name);
  637.   for(p = temporary_name, s = (char*)0; *p; p ++)
  638.     if(*p == '/') s = p;
  639.   strcpy((s ? s+1 : temporary_name), "lhXXXXXX");
  640.   mktemp(temporary_name);
  641. }
  642.  
  643. static void modify_filename_extention (char *buffer, char *ext)
  644. {
  645.   register char *p, *dot;
  646.  
  647.   for(p = buffer, dot = (char*)0; *p; p ++)
  648.   {
  649.     if(*p == '.')
  650.           dot = p;
  651.     else
  652.       if(*p == '/')
  653.             dot = (char*)0;
  654.   }
  655.  
  656.   if(dot) p = dot;
  657.   strcpy(p, ext);
  658. }
  659.  
  660. /* build backup file name */
  661. void build_backup_name(char *buffer, char *original)
  662. {
  663.   strcpy (buffer, original);
  664.   modify_filename_extention (buffer, BACKUPNAME_EXTENTION); /* ".bak" */
  665. }
  666.  
  667. void build_standard_archive_name(char *buffer, char *orginal)
  668. {
  669.   strcpy (buffer, orginal);
  670.   modify_filename_extention (buffer, ARCHIVENAME_EXTENTION); /* ".lzh" */
  671. }
  672.  
  673. /*----------------------------------------------------------------------*/
  674. /*                                    */
  675. /*----------------------------------------------------------------------*/
  676.  
  677. extern int patmatch();
  678.  
  679. boolean need_file(char *name)
  680. {
  681.   int i;
  682.  
  683.   if(cmd_filec == 0)
  684.     return TRUE;
  685.  
  686.   for(i = 0; i < cmd_filec; i ++)
  687.   {
  688.     if(patmatch(cmd_filev[i], name, 0 ))
  689.           return TRUE;
  690.   }
  691.  
  692.   return FALSE;
  693. }
  694.  
  695. FILE *xfopen (char *name, char *mode)
  696. {
  697.   FILE *fp;
  698.  
  699.   if((fp = fopen(name, mode)) == NULL)
  700.     fatal_error(name);
  701.  
  702.   return fp;
  703. }
  704.  
  705. /*----------------------------------------------------------------------*/
  706. /*                                    */
  707. /*----------------------------------------------------------------------*/
  708. int    archive_file_mode;
  709. int    archive_file_gid;
  710.  
  711. static boolean open_old_archive_1(char *name, FILE **v_fp)
  712. {
  713.   FILE *fp;
  714.   struct stat stbuf;
  715.  
  716.   if(stat (name, &stbuf) >= 0 && is_regularfile (&stbuf) && (fp = fopen (name, READ_BINARY)) != NULL)
  717.   {
  718.     *v_fp = fp;
  719.     archive_file_gid = stbuf.st_gid;
  720.     archive_file_mode = stbuf.st_mode;
  721.     return TRUE;
  722.   }
  723.  
  724.   *v_fp = NULL;
  725.   archive_file_gid = -1;
  726.   return FALSE;
  727. }
  728.  
  729. FILE *open_old_archive()
  730. {
  731.   FILE *fp;
  732.   char *p;
  733.  
  734.   if(!strcmp(archive_name, "-"))
  735.   {
  736.     if(cmd == CMD_EXTRACT || cmd == CMD_LIST)
  737.       return stdin;
  738.     else
  739.       return NULL;
  740.   }
  741.   if(p = (char *)rindex(archive_name,'.'))
  742.     {
  743.       if( strucmp(".LZH",p)==0
  744.           || strucmp(".LZS",p)==0
  745.           || strucmp(".COM",p)==0        /* DOS SFX */
  746.           || strucmp(".EXE",p)==0
  747.         || strucmp(".X"  ,p)==0        /* HUMAN SFX */
  748.           || strucmp(".BAK",p)==0 )    /* for BackUp */
  749.       {
  750.           open_old_archive_1 (archive_name, &fp );
  751.           return fp;
  752.       }
  753.     }
  754.  
  755.   if(open_old_archive_1 (archive_name, &fp))
  756.     return fp;
  757.  
  758.   sprintf( expanded_archive_name , "%s.lzh",archive_name);
  759.   if(open_old_archive_1 (expanded_archive_name, &fp))
  760.   {
  761.       archive_name = expanded_archive_name;
  762.       return fp;
  763.   }
  764.  
  765.   sprintf( expanded_archive_name, "%s.lzs",archive_name);
  766.   if(open_old_archive_1 (expanded_archive_name, &fp))
  767.   {
  768.       archive_name = expanded_archive_name;
  769.       return fp;
  770.   }
  771.   return NULL;
  772. }
  773.  
  774. int inquire(char *msg, char *name, char *selective)
  775. {
  776.   char buffer[1024];
  777.   char *p;
  778.  
  779.   for (;;)
  780.   {
  781.     fprintf (stderr, "%s %s ", name, msg);
  782.     fflush (stderr);
  783.  
  784.     fgets (buffer, 1024, stdin);
  785.  
  786.     for(p = selective; *p; p++)
  787.         if(buffer[0] == *p)
  788.           return p - selective;
  789.   }
  790.   /*NOTREACHED*/
  791. }
  792.  
  793. void write_archive_tail(FILE *nafp)
  794. {
  795.   putc (0x00, nafp);
  796. }
  797.  
  798. void copy_old_one(FILE *oafp, FILE*nafp, LzHeader *hdr)
  799. {
  800.   if(noexec)
  801.   {
  802.     fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  803.   }
  804.   else
  805.   {
  806.     reading_filename = archive_name;
  807.     writting_filename = temporary_name;
  808.     copyfile (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size,0);
  809.   }
  810. }
  811.